home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / etc / getwd.c < prev    next >
C/C++ Source or Header  |  1992-03-27  |  7KB  |  245 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #if defined(LIBC_SCCS) && !defined(lint)
  8. static char sccsid[] = "@(#)getwd.c    5.2 (Berkeley) 3/9/86";
  9. #endif LIBC_SCCS and not lint
  10.  
  11. /*
  12.  * getwd() returns the pathname of the current working directory. On error
  13.  * an error message is copied to pathname and null pointer is returned.
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include <sys/param.h>
  18. #include <sys/stat.h>
  19. #include <sys/dir.h>
  20. #include <sys/file.h>
  21.  
  22. #include <sprite.h>
  23. #include <fs.h>
  24. #include <sysStats.h>
  25.  
  26. #define GETWDERR(s)    (void) strcpy(pathname, (s));
  27.  
  28. static char *prepend();
  29.  
  30. extern char *strcpy();
  31. static int pathsize;            /* pathname length */
  32.  
  33. static char *oldGetwd();
  34.  
  35. char *
  36. getwd(pathname)
  37.     char *pathname;
  38. {
  39.     char pathbuf[MAXPATHLEN];        /* temporary pathname buffer */
  40.     char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
  41.     char curdir[MAXPATHLEN];        /* current directory buffer */
  42.     char *dptr = curdir;        /* directory pointer */
  43.     char *prepend();            /* prepend dirname to pathname */
  44.     int cdev;                /* current & root device number */
  45.     int cino;                /* current & root inode number */
  46.     int curServer;            /* current and root server ID */
  47.     DIR *dirp;                /* directory stream */
  48.     struct direct *dir;            /* directory entry struct */
  49.     Fs_Attributes d;            /* file status struct */
  50.     int fd;                /* Handle on current directory */
  51.     Ioc_PrefixArgs iocPrefix;        /* Returned by ioctl. */
  52.     ReturnStatus status;
  53.  
  54.     pathsize = 0;
  55.     *pnptr = '\0';
  56.     fd = open(".", O_RDONLY);
  57.     if (fd < 0) {
  58.     GETWDERR("getwd: can't open .");
  59.     }
  60.     status = Fs_IOControl(fd, IOC_PREFIX, 0, NULL, sizeof(Ioc_PrefixArgs), 
  61.         &iocPrefix);
  62.  
  63.     if (status != SUCCESS) {
  64.     /*
  65.      * If the ioctl fails assume we are on an old kernel and do it the
  66.      * old way.
  67.      */
  68. #if 0
  69.     printf("Using old getwd -- \"%s\".\n", Stat_GetMsg(status));
  70. #endif
  71.     return oldGetwd(pathname);
  72.     }
  73.     close(fd);
  74.     (void) strcpy(dptr, "./");
  75.     dptr += 2;
  76.     if (Fs_GetAttributes(curdir, FS_ATTRIB_FILE, &d) != SUCCESS) {
  77.         GETWDERR("getwd: can't stat .");
  78.         return (NULL);
  79.     }
  80.     for (;;) {
  81.     cino = d.fileNumber;
  82.     cdev = d.domain;
  83.     curServer = d.serverID;
  84.     (void) strcpy(dptr, "../");
  85.     dptr += 3;
  86.     if ((dirp = opendir(curdir)) == NULL) {
  87.         GETWDERR("getwd: can't open ..");
  88.         return (NULL);
  89.     }
  90.     Fs_GetAttributesID(dirp->dd_fd, &d);
  91.     if (curServer == d.serverID && cdev == d.domain) {
  92.         /*
  93.          * Parent directory is in the same domain as the current point.
  94.          * Check against root loop and then scan parent looking for match.
  95.          */
  96.         if (cino == d.fileNumber) {
  97.         /* reached root directory */
  98.         closedir(dirp);
  99.         break;
  100.         }
  101.         do {
  102.         if ((dir = readdir(dirp)) == NULL) {
  103.             closedir(dirp);
  104.             GETWDERR("getwd: read error in ..");
  105.             return (NULL);
  106.         }
  107.         } while (dir->d_ino != cino);
  108.         closedir(dirp);
  109.         pnptr = prepend("/", prepend(dir->d_name, pnptr));
  110.     } else {
  111.         /*
  112.          * The parent directory is in a different domain.  This means that
  113.          * the current point should be the root of a domain and this
  114.          * host should have a prefix that corresponds to it. 
  115.          * We already have the prefix from the ioctl, so just break.
  116.          */
  117.         closedir(dirp);
  118.         break;
  119.     }
  120.     }
  121.     if ((strcmp(iocPrefix.prefix, "/") != 0) || (*pnptr == 0)) {
  122.     pnptr = prepend(iocPrefix.prefix, pnptr);
  123.     }
  124.     (void) strcpy(pathname, pnptr);
  125.     return (pathname);
  126. }
  127.  
  128. /*
  129.  * prepend() tacks a directory name onto the front of a pathname.
  130.  */
  131. static char *
  132. prepend(dirname, pathname)
  133.     register char *dirname;
  134.     register char *pathname;
  135. {
  136.     register int i;            /* directory name size counter */
  137.  
  138.     for (i = 0; *dirname != '\0'; i++, dirname++)
  139.         continue;
  140.     if ((pathsize += i) < MAXPATHLEN)
  141.         while (i-- > 0)
  142.             *--pathname = *--dirname;
  143.     return (pathname);
  144. }
  145.  
  146. static char *
  147. oldGetwd(pathname)
  148.     char *pathname;
  149. {
  150.     char pathbuf[MAXPATHLEN];        /* temporary pathname buffer */
  151.     char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
  152.     char curdir[MAXPATHLEN];        /* current directory buffer */
  153.     char *dptr = curdir;        /* directory pointer */
  154.     char *prepend();            /* prepend dirname to pathname */
  155.     int cdev, rdev;            /* current & root device number */
  156.     int cino, rino;            /* current & root inode number */
  157.     int curServer, rootServer;        /* current and root server ID */
  158.     DIR *dirp;                /* directory stream */
  159.     struct direct *dir;            /* directory entry struct */
  160.     Fs_Attributes d;            /* file status struct */
  161.  
  162.     pathsize = 0;
  163.     *pnptr = '\0';
  164.     if (Fs_GetAttributes("/", FS_ATTRIB_FILE, &d) != SUCCESS) {
  165.         GETWDERR("getwd: can't stat /");
  166.         return (NULL);
  167.     }
  168.     rdev = d.domain;
  169.     rino = d.fileNumber;
  170.     rootServer = d.serverID;
  171.     (void) strcpy(dptr, "./");
  172.     dptr += 2;
  173.     if (Fs_GetAttributes(curdir, FS_ATTRIB_FILE, &d) != SUCCESS) {
  174.         GETWDERR("getwd: can't stat .");
  175.         return (NULL);
  176.     }
  177.     for (;;) {
  178.     if (d.fileNumber == rino && d.domain == rdev
  179.         && d.serverID == rootServer)
  180.         break;        /* reached root directory */
  181.     cino = d.fileNumber;
  182.     cdev = d.domain;
  183.     curServer = d.serverID;
  184.     (void) strcpy(dptr, "../");
  185.     dptr += 3;
  186.     if ((dirp = opendir(curdir)) == NULL) {
  187.         GETWDERR("getwd: can't open ..");
  188.         return (NULL);
  189.     }
  190.     Fs_GetAttributesID(dirp->dd_fd, &d);
  191.     if (curServer == d.serverID && cdev == d.domain) {
  192.         /*
  193.          * Parent directory is in the same domain as the current point.
  194.          * Check against root loop and then scan parent looking for match.
  195.          */
  196.         if (cino == d.fileNumber) {
  197.         /* reached root directory */
  198.         closedir(dirp);
  199.         break;
  200.         }
  201.         do {
  202.         if ((dir = readdir(dirp)) == NULL) {
  203.             closedir(dirp);
  204.             GETWDERR("getwd: read error in ..");
  205.             return (NULL);
  206.         }
  207.         } while (dir->d_ino != cino);
  208.         closedir(dirp);
  209.         pnptr = prepend("/", prepend(dir->d_name, pnptr));
  210.     } else {
  211.         /*
  212.          * The parent directory is in a different domain.  This means that
  213.          * the current point should be the root of a domain and this
  214.          * host should have a prefix that corresponds to it.  Scan the
  215.          * prefix table looking for a match.
  216.          */
  217.         register int index;
  218.         Fs_Prefix prefix;
  219.         closedir(dirp);
  220.         for (index=0 ; ; index++) {
  221.         bzero((char *) &prefix, sizeof(Fs_Prefix));
  222.         if (Sys_Stats(SYS_FS_PREFIX_STATS, index, (Address) &prefix)
  223.             != SUCCESS) {
  224.             sprintf(pathname,
  225.             "getwd: missing prefix %s", pnptr);
  226.             return(NULL);
  227.         }
  228.         if (prefix.serverID == curServer &&
  229.             prefix.domain == cdev &&
  230.             prefix.fileNumber == cino) {
  231.             pnptr = prepend(prefix.prefix, pnptr);
  232.             goto done;
  233.         }
  234.         }
  235.     }
  236.     }
  237. done:
  238.     if (*pnptr == '\0')    {    /* current dir == root dir */
  239.         (void) strcpy(pathname, "/");
  240.     } else {
  241.     strcpy(pathname, pnptr);
  242.     }
  243.     return (pathname);
  244. }
  245.